upcaster用來把舊版本event映射為新版本,有很多種不同實作方式,比如一版一版跳:1 -> 2 -> 3 ... -> 10
;或是直接跳:1 -> 10, 2 -> 10, ...
,各有不同的成本,在這先實作mapping到當前版本。
#[derive(Debug, Clone, Default)]
pub struct BookEventUpcaster;
impl EventUpcaster for BookEventUpcaster {
fn can_upcast(&self, event_type: &str, event_version: &str) -> bool {
true // 實際要依案例及應用情景,這裡先簡單帶過
}
fn upcast(&self, event: SerializedEvent) -> SerializedEvent {
println!("BookEventUpcaster: {:#?}", event);
let mut event_upcasted = event.clone();
match event.event_type.as_str() {
"BookEvent" => {
let mut payload = event.payload.clone();
// 取得 BookEvent::BookCreated 內容
let mut book_created = payload.get_mut("BookCreated");
if book_created.is_none() { return event_upcasted; }
let book_created = book_created.unwrap().as_object_mut().unwrap();
book_created.insert("author".to_string(), None::<String>.into());
event_upcasted.payload = payload;
}
_ => {}
}
event_upcasted
}
}
因為序列化Enum會帶Enum的選項,而在解析時險能當Json去parse,因為以SerializedEvent來說不知道具體的Event (struct/enum)為何。
SerializedEvent {
aggregate_id: "test-book-1",
sequence: 1,
aggregate_type: "Book",
event_type: "BookEvent",
event_version: "0.1.0",
payload: Object {
"BookCreated": Object {
"description": String("使用rust,併同cqrs框架,實現event sourcing"),
"id": String("test-book-1"),
"isbn10": String("1234567890"),
"title": String("Rust 語言開發實戰"),
},
},
metadata: Object {},
}
事件更新需要依不同的版本對應,如果比較複雜的情境,感覺還是需要先準備一個實際的enum / struct,把舊版的JSON值對應好後,再把這個enum / struct序列化為 payload。